/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import media from '@ohos.multimedia.media'
import Logger from '../model/Logger'
import mediaLibrary from '@ohos.multimedia.mediaLibrary'
import MediaUtils from '../model/MediaUtils'

const TAG: string = 'VideoPlayerUtils'

export default class VideoPlayerUtils {
    private videoPlayer = undefined
    private playPath: string = ''
    private surfaceID: string = ''
    private finishCallBack: () => void = undefined
    public statusChangedListener
    public playingProgressListener
    public mediaList: Array<mediaLibrary.FileAsset> = []
    private fileId: number
    public index: number = -1
    private fileAsset: mediaLibrary.FileAsset = undefined
    public isPlaying: boolean = false
    public intervalID = undefined
    public currentTimeMs: number = 0
    private fdPath: String = ''
    public fd: number = -1


    constructor(){
    }
    async createPlayer(){
        await this.release()
        Logger.info(TAG,'456')
        await media.createVideoPlayer().then((video) => {
            if (typeof(video) != 'undefined') {
                Logger.info(TAG,'video createVideoPlayer success')
                this.videoPlayer = video;

                Logger.info(TAG, 'createVideoPlayer')
                this.videoPlayer.on('playbackCompleted', () => { //Listens for video playback completed events.
                    Logger.info(TAG, 'play finish')
                    this.seek(0)
                    if (this.finishCallBack) {
                        this.finishCallBack()
                    }
                });
            } else {
                Logger.info(TAG,'video createVideoPlayer fail')
            }
        }).catch((error) => {
            Logger.info(TAG,`video catchCallback, error:${error.message}`)
        });

    }

    // 函数调用发生错误时用于上报错误信息
    failureCallback(error) {
        Logger.info(TAG,`error happened,error Name is ${error.name}`)
        Logger.info(TAG,`error happened,error Code is ${error.code}`)
        Logger.info(TAG,`error happened,error Message is ${error.message}`)
    }
    async initVideoPlayer(surfaceID,isPlayingFromStatus)  {
        this.surfaceID = surfaceID
        Logger.info(TAG,`this.videoPlayer:${JSON.stringify(this.videoPlayer)}`);
        Logger.info(TAG,`this.suraceID:${surfaceID}`);
        Logger.info(TAG, 'setDisplaySurface')
        await this.videoPlayer.setDisplaySurface(surfaceID).then(async ()=>{
            Logger.info(TAG,'setDisplaySurface success!');
            await this.videoPlayer.prepare().then(()=>{
                Logger.info(TAG,'prepare success!');
                if(isPlayingFromStatus!=null){
                    this.isPlaying = isPlayingFromStatus
                }else{
                    this.isPlaying = true
                }
            }).catch(err=>{
                Logger.info(TAG,'prepare fail!');
                Logger.info(TAG, 'isPlaying return false')
                this.isPlaying = false
            });
        }, this.failureCallback).catch(err=>{
            Logger.info(TAG,`setDisplaySurface fail!:${err}`);
            Logger.info(TAG, 'isPlaying return false')
            this.isPlaying= false
        })
        return this.isPlaying
    }

    play(seekTo, startPlay,callback) {
        Logger.info(TAG, `play seekTo= ${seekTo} startPlay= ${startPlay}`)
        //        this.notifyPlayingStatus(startPlay)
        if (startPlay) {
            if (seekTo < 0 && this.currentTimeMs > 0) {
                Logger.info(TAG, `pop seekTo= ${this.currentTimeMs}`)
                seekTo = this.currentTimeMs
            }
            let self = this
            this.videoPlayer.on('play', () => {
                Logger.info(TAG, `play() callback entered, player.state= ${self.videoPlayer.state}`)
                if (seekTo > 0) {
                    self.seek(seekTo)
                }
            })
            Logger.info(TAG, 'call player.play')
            this.videoPlayer.play((err) => {
                if (typeof (err) == 'undefined') {
                    Logger.info(TAG,'play success!');
                } else {
                    Logger.info(TAG,'play fail!');
                }
            })
            Logger.info(TAG, `player.play called player.state= ${this.videoPlayer.state}`)
        } else if (seekTo > 0) {
            this.currentTimeMs = seekTo
            callback()
            this.pause()
            Logger.info(TAG, `stash seekTo= ${this.currentTimeMs}`)
        } else {
            this.pause()
        }
    }

    async seek(time) {
        Logger.info(TAG, 'seek')
        if (typeof (this.videoPlayer) != 'undefined') {
            await this.videoPlayer.seek(time)
        }
    }

    getCurrentTime() {
        if (typeof (this.videoPlayer) != 'undefined') {
            return this.videoPlayer.currentTime
        }
        return 0
    }

    async pause() {
        Logger.info(TAG, 'pause')
        if (typeof (this.videoPlayer) != 'undefined') {
            await this.videoPlayer.pause()
        }
    }

    async stop() {
        Logger.info(TAG, 'stop')
        if (typeof (this.videoPlayer) != 'undefined') {
            await this.videoPlayer.stop()
        }
    }

    async resetToPlay() {
        if (typeof (this.videoPlayer) != 'undefined') {
            await this.videoPlayer.prepare().then(res=>{
                Logger.info(TAG, 'prepare success')
                this.videoPlayer.play().then(res=>{
                    Logger.info(TAG, 'play success')
                }).catch(err=>{
                    Logger.info(TAG, 'play error')
                })
            }).catch(err=>{
                Logger.info(TAG, 'prepare error')
            })

        }
    }

    async reset() {
        if (typeof (this.videoPlayer) != 'undefined') {
            await this.videoPlayer.reset()
            Logger.info(TAG, 'reset success')
        }
    }
    async release() {
        if (typeof (this.videoPlayer) != 'undefined') {
            await this.videoPlayer.release()
            Logger.info(TAG, 'release success')
        }
    }

    setFinishCallBack(callback) {
        this.finishCallBack = callback
    }

    setOnStatusChangedListener(callback) {
        this.statusChangedListener = callback
    }

    setOnPlayingProgressListener(callback) {
        this.playingProgressListener = callback
    }

    cancelTimer() {
        if (typeof (this.intervalID) !== 'undefined') {
            Logger.info(TAG, `clear update interval ${this.intervalID}`)
            clearInterval(this.intervalID)
            this.intervalID = undefined
        }
    }

    notifyPlayingStatus(isPlaying) {
        this.isPlaying = isPlaying
        //        this.statusChangedListener(this.isPlaying) //在这个里面就是去加载PlayingProgress监听，并且改变播放按钮图标
        Logger.info(TAG, `notifyPlayingStatus isPlaying= ${isPlaying} intervalId= ${this.intervalID}`)
        if (isPlaying) {
            if (typeof (this.intervalID) === 'undefined') {
                this.intervalID = setInterval(() => {//每0.5秒获取一次当前播放位置
                    if (typeof (this.playingProgressListener) !== 'undefined' && this.playingProgressListener !== null) {
                        let timeMs = this.getCurrentTime()
                        this.currentTimeMs = timeMs
                        if (typeof (timeMs) === 'undefined') {
                            timeMs = 0
                        }
                        Logger.info(TAG, `player.currentTime= ${timeMs}`)
                        this.playingProgressListener(timeMs)//把当前的播放时间和进度处理好显示出来
                    }
                }, 500)
                Logger.info(TAG, `set update interval ${this.intervalID}`)
            }
        } else {
            this.cancelTimer()
        }
    }


    async preLoad(index, callback) {
        Logger.info(TAG, `preLoad ${index}/${this.mediaList.length}`)
        if (index < 0 || index >= this.mediaList.length) {
            Logger.error(TAG, 'preLoad ignored')
            return 0
        }
        this.index = index

        await this.mediaList[this.index].open('r').then((fd) => {
            Logger.info(TAG, `player= ${JSON.stringify(this.videoPlayer)}`)
            Logger.info(TAG, `player.state= ${this.videoPlayer.state}`)
            this.fd=fd
            this.fdPath='fd://' + fd

            if (this.fdPath === this.videoPlayer.url && this.videoPlayer.state !== 'idle') {//已经在播放当前音乐
                Logger.info(TAG, 'preLoad finished. url not changed')
                callback()
            } else if (this.videoPlayer.state === 'idle') {  //表示当前没有在播放音乐
                if (typeof (this.fdPath) === 'undefined') {
                    return 0
                }
                Logger.info(TAG, `player.url= ${this.videoPlayer.url}`)
                this.videoPlayer.url = this.fdPath //触发上面的dataLoad监听
                callback()
                return 0
            } else {//表示当前在播放其他音乐
                Logger.info(TAG, 'player.reset')
                this.videoPlayer.reset().then((res)=>{
                    Logger.info(TAG, 'reset success')
                    this.videoPlayer.url = this.fdPath
                    callback()
                    return 0
                }).catch(err=>{
                    Logger.error(TAG, 'reset error')
                })
                Logger.info(TAG, `player.reset done, state= ${this.videoPlayer.state}`)
            }
        }).catch((err) => {
            Logger.info(TAG,`File err!  ${err}`)
        });

        Logger.info(TAG, `preLoad ${this.fdPath} end`)
        return 0
    }

    async restorePlayingStatus(status, callback) {
        Logger.info(TAG, `restorePlayingStatus ${JSON.stringify(status)}`)
        Logger.info(TAG, `*****1111this.mediaList::${JSON.stringify(this.mediaList.length)}`)
        for (let i = 0; i < this.mediaList.length; i++) {
            Logger.info(TAG, `*****this.mediaList[i].id::${JSON.stringify(this.mediaList[i].id)}`)
            Logger.info(TAG, `*****status.fileId::${JSON.stringify(status.fileId)}`)
            if (this.mediaList[i].displayName == status.displayName) { //最初的运行，这里估计一次都进不去
                Logger.info(TAG, `restore to index ${i}`)
                await this.preLoad(i, () => {//给视频播放器传入播放路径 this.videoPlayer.url = this.fdPath
                    Logger.info(TAG, 'restore play status')
                    callback(i,status.seekTo)
                })
                return
            }
        }
        Logger.info(TAG, 'restorePlayingStatus failed')
        callback(-1)
    }

    async getMediaList(fileId,callback) {
        this.fileId=fileId //赋值当前视频id
        this.mediaList = []
        Logger.info(TAG, `aboutToAppear,id=${this.fileId}`)
        let fileAsset1 = MediaUtils.getFileAssetsFromType(mediaLibrary.MediaType.VIDEO)
        //        Logger.info(TAG, `fileAssetName=${fileAsset1}`)
        await fileAsset1.then(fileList => {
            Logger.info(TAG, 'getFileList callback')
            this.mediaList = fileList
            Logger.info(TAG, `*****this.mediaList::${JSON.stringify(this.mediaList.length)}`)
            if (this.fileId != -1) {
                this.mediaList.forEach((file, index) => {
                    Logger.info(TAG, `file.id=${file.id}`)
                    if (file.id === this.fileId) {
                        this.fileAsset = file
                        callback(file,index)
                    }
                })
            }
            callback()
        }).catch(err => {
            Logger.error(TAG, `getFileList err,err = ${err}`)
        })
    }

    getDuration() {
        Logger.info(TAG, `getDuration index= ${this.index}`)
        if (this.mediaList[this.index].duration > 0) {
            return this.mediaList[this.index].duration
        }
        //        Logger.info(TAG, `getDuration state= ${this.mediaList.state}`)
        if (this.videoPlayer.state === 'idle') {//就是当前没有音频文件在播放，所以时长为0，播放器状态也是空闲的，时长也设为0
            Logger.warn(TAG, `getDuration ignored player.state= ${this.videoPlayer.state}`)
            return 0
        }
        //        this.mediaList[this.index].duration = Math.min(this.player.duration, 97615)//最大音频时长，一天多
        //        Logger.info(TAG, `getDuration player.src= ${this.player.src} player.duration= ${this.playlist.audioFiles[this.index].duration} `)
        return this.mediaList[this.index].duration
    }

    setPlaySpeed(speed){
        if (this.videoPlayer.state === 'idle') {
            //            Logger.warn(TAG, `getDuration ignored player.state= ${this.videoPlayer.state}`)
            return
        }

        this.videoPlayer.setSpeed(speed)
    }
}